package com.hxs.hxsserver.service.impl;


import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.IdWorker;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.hxs.hxsserver.domain.dto.IdDTO;
import com.hxs.hxsserver.domain.dto.user.ChangePasswordDTO;
import com.hxs.hxsserver.domain.dto.user.QueryUserListDTO;
import com.hxs.hxsserver.domain.dto.user.UpdateUserDTO;
import com.hxs.hxsserver.domain.entity.device.Device;
import com.hxs.hxsserver.domain.entity.device.DeviceFolder;
import com.hxs.hxsserver.domain.entity.device.Factor;
import com.hxs.hxsserver.domain.entity.user.Menu;
import com.hxs.hxsserver.exception.ApiException;
import com.hxs.hxsserver.mapper.device.DeviceFolderMapper;
import com.hxs.hxsserver.mapper.device.DeviceMapper;
import com.hxs.hxsserver.mapper.device.FactorMapper;
import com.hxs.hxsserver.mapper.user.MenuMapper;
import com.hxs.hxsserver.service.UserService;
import com.hxs.hxsserver.utils.*;
import com.hxs.hxsserver.config.redis.RedisService;
import com.hxs.hxsserver.config.redis.UserKey;
import com.hxs.hxsserver.domain.dto.ResponseCode;
import com.hxs.hxsserver.domain.dto.user.PasswordLoginDTO;

import com.hxs.hxsserver.domain.entity.user.User;
import com.hxs.hxsserver.domain.vo.UserLoginVO;
import com.hxs.hxsserver.domain.vo.UserVO;
import com.hxs.hxsserver.mapper.user.UserMapper;
import com.wf.captcha.SpecCaptcha;
import com.wf.captcha.base.Captcha;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import java.util.stream.Collectors;


/**
 * 用户Service
 */
@Service
@Slf4j
public class UserServiceImpl extends ServiceImpl<UserMapper, User> implements UserService {

    @Resource
    private RedisService redisService;
    @Resource
    private HttpServletRequest request;
    @Resource
    private DozerUtil dozerUtil;
    @Resource
    private UserMapper userMapper;
    @Resource
    private MenuMapper menuMapper;
    @Resource
    private DeviceFolderMapper folderMapper;
    @Resource
    private DeviceMapper deviceMapper;
    @Resource
    private FactorMapper factorMapper;

    @Override
    public User selectByUsername(String email) {
        LambdaQueryWrapper<User> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(User::getLoginName, email);
        queryWrapper.eq(User::getIsDelete,0);
        return this.baseMapper.selectOne(queryWrapper);
    }


    @Override
    public UserLoginVO passwordLogin(PasswordLoginDTO dto) {
        User user = selectByUsername(dto.getLoginName());
        if (user == null) {
            throw new ApiException(ResponseCode.LOGIN_USER_ERROR.getCode(), ResponseCode.LOGIN_USER_ERROR.getDesc());
        }
        if (!PasswordUtils.passwordVerify(dto.getPassword(), user.getPassword())) {
            throw new ApiException(ResponseCode.PASSWORD_ERROR.getCode(), ResponseCode.PASSWORD_ERROR.getDesc());
        }
        if (!captchaVer(dto.getPicKey(), dto.getPicCode())) {
            throw new ApiException(ResponseCode.PIC_CODE_ERROR.getCode(), ResponseCode.PIC_CODE_ERROR.getDesc());
        }
        //用户被禁止登录
        if (user.getStatus() != 1) {
            throw new ApiException(ResponseCode.LOGIN_FORBIDDEN.getCode(), ResponseCode.LOGIN_FORBIDDEN.getDesc());
        }

        String token = JwtTokenUtil.generateToken(user.getId(), user.getLoginName());
        redisService.set(UserKey.userToken, token, token);

        UserVO userVO = dozerUtil.map(user, UserVO.class);
        return new UserLoginVO() {{
            setToken(token);
            setUserInfo(userVO);
        }};
    }


    @Override
    public UserVO userInfo(Integer userId) {
        User user = this.baseMapper.selectById(userId);
        return dozerUtil.map(user, UserVO.class);
    }

    @Override
    public Object getPicCode() {
        SpecCaptcha specCaptcha = new SpecCaptcha(100, 50, 4);
        specCaptcha.setCharType(Captcha.TYPE_NUM_AND_UPPER);
        String imgBase64 = specCaptcha.toBase64();
        String codeKey = IdWorker.getIdStr();

        redisService.set(UserKey.picCode, codeKey, specCaptcha.text().toLowerCase());
        JSONObject obj = new JSONObject();
        obj.put("codeKey", codeKey);
        obj.put("imgBase64", imgBase64);
        log.info("ver code: {}", specCaptcha.text().toLowerCase());
//        Device device = deviceMapper.selectById(54);
//        for (int i = 0; i < 192; i++) {
//            device.setDeviceName("测试设备"+String.format("%02X", (9+i)));
//            device.setId(null);
//            device.setDeviceStatus(0);
//            String address = "A0000002"+String.format("%02X", (9+i));
//            device.setDeviceHardwareAddr(address);
//            deviceMapper.insert(device);
//            redisService.set(UserKey.deviceAddr,address,address);
//            Factor factor =new Factor();
//            factor.setSort(1);
//            factor.setDeviceHardwareAddr(address);
//            factor.setDataType("16");
//            factor.setCoefficient("0.1");
//            factor.setDeviation("0");
//            factor.setDigit(1);
//            factor.setNodeNo(1);
//            factor.setUnit("C");
//            factor.setFactorName("温度");
//            factorMapper.insert(factor);
//            Factor factor2 =new Factor();
//            factor2.setSort(2);
//            factor2.setDeviceHardwareAddr(address);
//            factor2.setDataType("16");
//            factor2.setCoefficient("0.1");
//            factor2.setDeviation("0");
//            factor2.setDigit(1);
//            factor2.setNodeNo(2);
//            factor2.setUnit("C");
//            factor2.setFactorName("湿度");
//            factorMapper.insert(factor2);
//        }
        return obj;
    }

    @Override
    public Boolean changePassword(ChangePasswordDTO dto,Integer userId) {
        User user = this.baseMapper.selectById(userId);
        if (!PasswordUtils.passwordVerify(dto.getOldPassword(), user.getPassword())) {
            throw new ApiException(ResponseCode.OLD_PASSWORD_ERROR.getCode(), ResponseCode.OLD_PASSWORD_ERROR.getDesc());
        }
        user.setPassword(PasswordUtils.passwordEncrypt(dto.getNewPassword()));
        this.updateById(user);
        return true;
    }

    @Override
    public Boolean updateUser(UpdateUserDTO dto, Integer userId) {
        dto.setId(userId);
        if (dto.getPassword()!=null){
            dto.setPassword(PasswordUtils.passwordEncrypt(dto.getPassword()));
        }
        return this.updateById(dozerUtil.map(dto, User.class));
    }

    private boolean captchaVer(String picKey, String picCode) {
        String code = redisService.get(UserKey.picCode, picKey, String.class);
        if (code != null){
            redisService.delete(UserKey.picCode,picKey);
        }
        return picCode.equalsIgnoreCase(code);
    }


    @Override
    public IPage<UserVO> getUserList(QueryUserListDTO queryUserListDTO, User user) {
        Integer userId =null;
        //如果是超级管理员就不加过滤条件
        if(user.getRoleId()!=1){
            userId = user.getId();
        }
        Page<UserVO> page = new Page<>(queryUserListDTO.getPage(), queryUserListDTO.getSize());
        IPage<UserVO> deviceDTOIPage = userMapper.getUserList(page,queryUserListDTO,userId);
        return deviceDTOIPage;
    }

    @Override
    public List<UserVO> getUserListByAlarm(User user) {
        List<UserVO> deviceDTOIPage = userMapper.getUserListByAlarm(user.getId());
        return deviceDTOIPage;
    }

    @Override
    public Boolean deleteUserById(IdDTO idDTO, User userLogin) {
        User user = userMapper.selectById(idDTO);
        LambdaUpdateWrapper<User> updateWrapper = new LambdaUpdateWrapper<>();
        updateWrapper.eq(User::getId, idDTO.getId());
        updateWrapper.set(User::getIsDelete,1);
        baseMapper.update(null,updateWrapper);
        if(userLogin.getRoleId()==1 && user.getRoleId()==2){
            //如果是超级管理员删除管理员
            //删除管理员创建的文件及设备及下属人员
            DeviceFolder deviceFolder = folderMapper.selectById(user.getFolderId());
            LambdaQueryWrapper<DeviceFolder> queryWrapper = new LambdaQueryWrapper<>();
            queryWrapper.likeRight(DeviceFolder::getLayer, deviceFolder.getLayer());
            List<DeviceFolder> deviceFolders = folderMapper.selectList(queryWrapper);
            List<Integer> collect = deviceFolders.stream()
                    .map(DeviceFolder::getId)
                    .collect(Collectors.toList());
            LambdaQueryWrapper<Device> deviceLambdaQueryWrapper = new LambdaQueryWrapper<>();
            deviceLambdaQueryWrapper.in(Device::getFolderId,collect);
            //删除设备
            int delete = deviceMapper.delete(deviceLambdaQueryWrapper);
            //删除文件夹
            int delete1 = folderMapper.delete(queryWrapper);
            //删除用户
            LambdaUpdateWrapper<User> updateWrapper2 = new LambdaUpdateWrapper<>();
            updateWrapper.eq(User::getParentId, idDTO.getId());
            updateWrapper.set(User::getIsDelete,1);
            baseMapper.update(null,updateWrapper2);
        }else {
            //把该用户创建的文件都赋值给他的上一级
            LambdaUpdateWrapper<DeviceFolder> updateWrapper1 = new LambdaUpdateWrapper<>();
            updateWrapper1.eq(DeviceFolder::getCreateUserId,idDTO);
            updateWrapper1.set(DeviceFolder::getCreateUserId,user.getParentId());
            folderMapper.update(null,updateWrapper1);
        }
        return null;
    }

    @Override
    public List<Menu> getMenuList(Integer userId) {
        User user = userMapper.selectById(userId);
        String[] split = user.getMenus().split(",");
        List<String> labels = Arrays.asList(split);
        if(user.getRoleId()==2){
            //如果是管理，取消系统管理可选项
            labels = labels.stream()
                     .filter(label -> !label.contains("/system/user"))
                     .collect(Collectors.toList());
        }
        LambdaQueryWrapper<Menu> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.in(Menu::getLabel, labels);
        return  menuMapper.selectList(queryWrapper);
    }

    @Override
    public Boolean insertUser(UpdateUserDTO dto, User user) {
        LambdaQueryWrapper<User> userLambdaQueryWrapper = new LambdaQueryWrapper<>();
        userLambdaQueryWrapper.eq(User::getLoginName,dto.getLoginName());
        userLambdaQueryWrapper.eq(User::getIsDelete,0);
        List<User> users = userMapper.selectList(userLambdaQueryWrapper);
        if (users.size()>0){
            throw new ApiException(ResponseCode.LOGIN_NAME_EXISTS_ERROR.getCode(), ResponseCode.LOGIN_NAME_EXISTS_ERROR.getDesc());
        }
        User newUser = dozerUtil.map(dto, User.class);
        newUser.setParentId(user.getId());
        DeviceFolder deviceFolder2 = new DeviceFolder();
        if(user.getRoleId()==1){
            newUser.setRoleId(2);
            LambdaQueryWrapper<DeviceFolder> deviceFolderLambdaQueryWrapper = new LambdaQueryWrapper<>();
            deviceFolderLambdaQueryWrapper.eq(DeviceFolder::getParentId, user.getFolderId())
                    .orderByDesc(DeviceFolder::getLayer) // 按 layer 降序排序
                    .last("LIMIT 1");
            DeviceFolder deviceFolder = folderMapper.selectOne(deviceFolderLambdaQueryWrapper);
            if(deviceFolder!=null){
                deviceFolder2.setLayer(deviceFolder.getLayer()+1);
            }else {
                DeviceFolder deviceFolder1 = folderMapper.selectById(user.getFolderId());
                deviceFolder2.setLayer(deviceFolder1.getLayer()*1000+101);
            }
            deviceFolder2.setCreateUserId(newUser.getId());
            deviceFolder2.setParentId(user.getFolderId());
            deviceFolder2.setFolderName(dto.getLoginName());
            folderMapper.insert(deviceFolder2);
            newUser.setFolderId(deviceFolder2.getId());
        }else if(user.getRoleId()==2){
            newUser.setRoleId(3);
            newUser.setFolderId(user.getFolderId());
        }
        newUser.setPassword(PasswordUtils.passwordEncrypt(dto.getPassword()));
        int insert = userMapper.insert(newUser);
        //更新文件夹创建者为当前新增用户
        deviceFolder2.setCreateUserId(newUser.getId());
        folderMapper.updateById(deviceFolder2);
        return true;
    }

    @Override
    public List<Integer> getUsersId(User user) {
        LambdaQueryWrapper<User> lambdaQueryWrapper = new LambdaQueryWrapper<>();
        lambdaQueryWrapper.select(User::getId);

        if (user.getRoleId() == 1) {
            return userMapper.selectList(lambdaQueryWrapper)
                    .stream()
                    .map(User::getId)
                    .collect(Collectors.toList());
        }

        if (user.getRoleId() == 2) {
            lambdaQueryWrapper.eq(User::getParentId, user.getId());
            List<Integer> usersId = userMapper.selectList(lambdaQueryWrapper)
                    .stream()
                    .map(User::getId)
                    .collect(Collectors.toList());
            usersId.add(user.getId());
            return usersId;
        }

        if (user.getRoleId() == 3) {
            return Collections.singletonList(user.getId());
        }

        return Collections.emptyList(); // 使用空列表而不是 null
    }
}
